/**
 * @fileoverview Share Tools view.
 * @author Jonathan Hensley <jhensley@gannett.com>
 */
define([
    'jquery',
    'underscore',
    'backbone',
    'pubsub',
    'app',
    'facebook',
    'state'
],
function(
    $,
    _, 
    Backbone,
    PubSub,
    App,
    Facebook,
    StateManager
) {

    /**
     * View class.
     */
    var ShareToolsView = Backbone.View.extend({

        // Events.
        events: {
            'click .share-tab': 'onClickShareTab',
            'click .fb-post-btn': 'onClickFbPost',
            'click .social-networks .svc-btn': 'onClickSvcBtn',
            'click .cta .cancel': 'onClickCancel',
            'click .cta .send': 'onClickSend',
            'submit .share-email-form': 'onSubmitEmailForm'
        },

        /**
         * Initialize view.
         */
        initialize: function() {
            _.bindAll(this, 'toggle', 'fbShareCallback', 'twTweetListener');
            this.subviews = {};
            this.toggle(this.options.event);
        },

        /**
         * Click handler for 'send' button.
         */
        onClickSend: function(e) {
            this.$emailForm.trigger('submit');
        },

        /**
         * Submit handler for 'email' form.
         */
        onSubmitEmailForm: function(e) {
            e.preventDefault();
            if (this.isValid(this.$emailForm)) {
                $.ajax({
                    type: 'POST',
                    url: this.$emailForm.attr('action'),
                    data: this.$emailForm.serialize()
                }).done(_.bind(function(response) {
                    this.$container.hide();
                    this.$('.email-success').show();
                    PubSub.trigger('uotrack', 'UtilityBarShareEmail');
                    // console.log('submit response', response);
                    // TODO: Add error checking when endpoint is fixed.
                    // TODO: Add stock text/link to email body.
                }, this));
            }
        },

        /**
         * Validate email form.
         */
        isValid: function($form) {
            // TODO: Add validation for email addresses if possible.
            var valid = true;
            $form.children('input,textarea').removeClass('error').each(function(index, el) {
                var $el = $(el);
                if ($el.hasClass('required') && $el.val() === '') {
                    $el.addClass('error');
                    valid = false;
                }
            });
            return valid ? true : false;
        },

        /**
         * Click handler for 'cancel' button.
         */
        onClickCancel: function(e) {
            this.toggle(undefined, true);
        },

        /**
         * Click handler for social media services buttons.
         */
        onClickSvcBtn: function(e) {
            e.preventDefault();
            var $currentTarget = $(e.currentTarget);
            var shareLink = $currentTarget.data('href');
            var service = $currentTarget.data('service');
            if (service === 'google+') {
                this.gpShare(shareLink);
            } else if (service === 'linkedin') {
                this.liShare(shareLink);
            }
        },

        /**
         * Click handler for share tabs.
         */
        onClickShareTab: function(e) {
            this.$('.share-tab, .share-pane').removeClass('active');
            var $currentTarget = $(e.currentTarget);
            $currentTarget.addClass('active');
            if ($currentTarget.hasClass('social-tab')) {
                this.$('.social-pane').addClass('active');
            } else {
                this.$('.email-pane').addClass('active');
            }
        },

        /**
         * Load twitter library on-demand and start listening for tweets.
         */
        twInit: function() {
            var twBtn = this.$('.svc-btn.tw');
            var twIntentUrl = twBtn.attr('href');
            if (twIntentUrl.match(/&text=&/gi)) {
                twBtn.attr('href', twIntentUrl.replace(/&text=&/gi, '&text=' + encodeURI(this.pageInfoObj.seotitletag) + '&'));
            }
            App.loadScript('//platform.twitter.com/widgets.js', 'twttr',
                this.twTweetListener);
        },

        /**
         * Listen for tweet event to update share pane.
         */
        twTweetListener: function() {
            twttr.widgets.load();
            this.tweetListener = true;
            twttr.events.bind('tweet', _.bind(function(event) {
                this.$container.hide();
                this.$('.twitter-success').show();
                PubSub.trigger('uotrack', 'UtilityBarShareTweet');
            }, this));
        },

        /**
         * Open popup for sharing on Google+.
         * @param {string} shareLink Link to share on Google+.
         */
        gpShare: function(shareLink) {
            PubSub.trigger('uotrack', 'UtilityBarShareGooglePlus');
            App.openPopup('https://plus.google.com/share?url=' +
                encodeURI(this.link), 600, 500);
        },

        /**
         * Open popup for sharing on LinkedIn.
         * @param {string} shareLink Link to share on LinkedIn.
         */
        liShare: function(shareLink) {
            PubSub.trigger('uotrack', 'UtilityBarShareLinkedIn');
            App.openPopup('https://www.linkedin.com/cws/share?url=' +
                encodeURI(this.link), 600, 400);
        },

        /**
         * Click handler for 'post to facebook' button.
         */
        onClickFbPost: function(e) {
            this.fbAuthorized ? this.fbShare() : this.fbLogin();
        },

        /**
         * Check login status when opening share flyout. If user is logged in,
         *     check permissions.  If all is good, don't call FB.login when
         *     post button is clicked.
         */
        fbCheckLoginStatus: function() {
            this.fbCheckOnly = true;

            Facebook.getFB(_.bind(function(FB) {

                FB.getLoginStatus(_.bind(function(response) {
                    // console.log('fbCheckLoginStatus', response)

                    // User is logged in, check permissions for posting.
                    if (response.status === 'connected') {
                        this.fbCheckPermissions(response.authResponse.accessToken);
                    }

                }, this), true);

            }, this));
        },

        /**
         * Check user's permission for posting to feed. Also fetch user's profile
         *     link to use for linking to feed post.
         */
        fbCheckPermissions: function(accessToken) {

            Facebook.getFB(_.bind(function(FB) {

                FB.api('/me/permissions',
                    {'access_token': accessToken},
                    _.bind(function(response){
                        // console.log('fbCheckPermissions', response);
                        if (response.data && response.data.length) {
                            var hasPermission = false;
                            for (var prop in response.data[0]) {
                                if (prop.match('publish_stream|publish_actions')) {
                                    hasPermission = true;
                                    break;
                                }
                            }
                            if (hasPermission) {
                                this.fbAuthorized = true;
                                if (!this.fbCheckOnly) this.fbShare();
                                this.fbCheckOnly = false;
                            } else if (this.fbLoginAttempted) {
                                this.$fbLoading.hide();
                                this.$status.text('You must allow posting on your behalf, try again.');
                            }
                        }
                    }, this)
                );

                FB.api('/me',
                    {'access_token': accessToken},
                    _.bind(function(response){
                        // console.log('fbMe', response);
                        if (response.link) this.fbLink = response.link;
                    }, this)
                );


            }, this));

            
        },

        /**
         * Prompt user to login with publishing permissions.
         */
        fbLogin: function () {
            this.fbCheckOnly = false;
            this.fbLoginAttempted = true;
            this.$status.text('');
            this.$fbLoading.show();

            Facebook.getFB(_.bind(function(FB) {
        
                FB.login(_.bind(function(response) {

                    if (response.authResponse) {
                        this.fbCheckPermissions(response.authResponse.accessToken);
                    } else {
                        this.$fbLoading.hide();
                        this.$status.text('You must login with Facebook, try again.');
                    }

                }, this), {scope: 'publish_stream'});

            }, this));
                        
        },

        /**
         * Share current story to feed.
         */
        fbShare: function() {
            this.$fbLoading.show();

            var obj = {
              link: this.link,
              picture: this.image,
              type: 'link',
              name: this.title,
              description: this.$socialMessage.val()
            };

            Facebook.getFB(_.bind(function(FB) {
                FB.api('/me/feed/', 'post', obj, this.fbShareCallback);
            }, this));
            
        },

        /**
         * Check for error or success on posting in this callback.
         * @param {Object} repsonse Feed post response.
         */
        fbShareCallback: function(response) {
            // console.log('fbShareCallback', response);
            if (response.error) {
                this.fbAuthorized = false;
                this.$fbLoading.hide();
                this.$status.text('An error occurred, try again.');
            } else {
                this.$('.post-link').remove();
                if (response.id && this.fbLink) {
                    var linkUrl = this.fbLink + '/posts/' + response.id.replace(/.*_(.*)/gi, '$1');
                    var link = $('<a target="_blank" class="post-link" href="' +
                        linkUrl + '">View the post.</a>')
                        .on('click',
                            _.bind(function(){
                                App.openPopup(linkUrl, 1000, 600);
                            }, this)
                        );
                    this.$('.facebook-success p').append(link);
                }
                this.$fbLoading.hide();
                this.$container.hide();
                this.$('.facebook-success').show();
                PubSub.trigger('uotrack', 'UtilityBarShareFacebook');
                this.fbLink = undefined;
            }
        },

        /**
         * Toggle the share panel open/closed.
         * @param {Event} e Browser event.
         * @param {boolean=} close Force close.
         */
        toggle: function(e, close) {
            this.$btn = this.$('.btn');
            this.$container = this.$('.container');
            close = close || this.$btn.hasClass('open');
            if (e) {
                var $target = $(e.target);
                if ($target.closest(this.$container).length ||
                    $target.closest(this.$('.success-pane')).length) {
                        return;
                }
            }
            if (close) {
                this.$btn.removeClass('open');
                this.$flyout.removeClass('open');
                this.$('.success-pane').hide();
                this.$container.show();
                this.$('.social-tab').trigger('click');
                this.destroy();
            } else if (close === false) {
                this.pageInfoObj = StateManager.getCurrentPageInfo();
                this.$body = App.get('body');

                // Avoid triggering the body click being added below. But simulate
                // a click to avoid unwanted stopped propagation for other open
                // flyouts.
                this.$body.trigger('click');
                if (e) e.stopPropagation();
                this.$flyout = this.$('.flyout-share');
                this.$socialMessage = this.$('.social-message');
                this.$status = this.$('.status .text');
                this.$fbLoading = this.$('.fb-loading');
                this.$emailForm = this.$('.share-email-form');
                var titleTag = this.$('.this-story h4');
                this.title = titleTag.text();
                if (!this.title){
                    this.title = document.title;
                    titleTag.text(this.title);
                }
                var objShareImage = this.$('.story-pic');
                App.lazyLoadImage(objShareImage, 'data-src', true);
                this.image = objShareImage.attr('data-share-image');
                this.link = 'http://www.usatoday.com' + window.location.pathname;
                this.fbCheckLoginStatus();
                this.twInit();
                this.$btn.addClass('open');
                this.$flyout.addClass('open');
                PubSub.trigger('uotrack', 'UtilityBarShareOpen'); 
                this.$body.on('click.' + this.cid, this.toggle);
            }
        },

        /**
         * Clean up view.
         * Removes event handlers and element (optionally).
         * @param {boolean} removeEl option to also remove View from DOM.
         */
        destroy: function(removeEl) {
            if (this.tweetListener) twttr.events.unbind('tweet');
            this.$body.off('click.' + this.cid);
            this.undelegateEvents();
            _.each(this.subviews, function(view){
                if (typeof view.destroy !== 'undefined') {
                    view.destroy(removeEl);
                }
            });
            if (removeEl) {this.remove();}
        }
    });

    /**
     * Return view class.
     */
    return ShareToolsView;
});
